package jumavidesktop.Persistencia.Dao.Implementaciones;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.persistence.EntityManager;
import jumavidesktop.Otros.Pojos.MyRespuesta;
import jumavidesktop.Otros.Pojos.consNamed;
import jumavidesktop.Persistencia.Dao.AbstractDAO;
import jumavidesktop.Persistencia.Dao.Interfaces.IDaoMatriculas;
import jumavidesktop.Persistencia.Dao.Interfaces.IDaoUsuarios;
import jumavidesktop.Persistencia.Dao.WrapperTransaction;
import jumavidesktop.Persistencia.entidades.Matricula;
import jumavidesktop.Persistencia.entidades.Usuario;
import org.apache.commons.lang.StringUtils;

/**
 *
 * @author vimso
 */
public class DaoUsuario extends AbstractDAO<Usuario> implements IDaoUsuarios {

    public DaoUsuario() {
        super();
    }
    //<editor-fold defaultstate="expanded" desc="Contructores">

    public DaoUsuario(EntityManager entityManager) {
        super(entityManager);
    }

    //</editor-fold>
    //<editor-fold defaultstate="collapsed" desc="Implementaciones por herencia">
    @Override
    public MyRespuesta verificarEntidadAlGuardar(Usuario entidad) {
        MyRespuesta respuesta = this.verificarDatosMinimos(entidad);

        if (!respuesta.getTodoOK()) {

            DaoUsuario daouser = new DaoUsuario(this.entityManager);
            //Busco si hay algun usuario con ese DNI

            consNamed consulta = new consNamed();
            consulta.setNamedQuery(Usuario.BUSCAR_POR_DNI);
            consulta.addParametros(Usuario.PA_BUSCAR_DNI, entidad.getDni());

            if (conNamedQuery(consulta).size() > 0) {
                respuesta.addError("Ya existe un suario con el D.N.I.: ");
            }
        }

        if (respuesta.getTodoOK() && entidad.getMatriculaList().size() > 0) {
            //Verifico las entidades hijas    
            IDaoMatriculas daoMatriculas = new DaoMatriculas(this.entityManager);
            for (Matricula elemento : entidad.getMatriculaList()) {
                respuesta.agregarMyRespuesta(daoMatriculas.verificarEntidadAlGuardar(elemento));
            }
        }
        return respuesta;
    }

    @Override
    public MyRespuesta verificarDatosMinimos(Usuario entidad) {

        //Se ha de especificar el nombre y el DNI
        MyRespuesta res = new MyRespuesta();

        if (StringUtils.isBlank(entidad.getNombre())) {
            res.addError("Se debe especificar el nombre del usuario");
        }

        if (StringUtils.isBlank(entidad.getDni())) {
            res.addError("Se debe especificar el DNI del usuario");
        }
        return res;
    }

    @Override
    public MyRespuesta verificarEntidadAlModificar(Usuario entidad) {
        MyRespuesta respuesta = this.verificarDatosMinimos(entidad);
        if (respuesta.getTodoOK() && entidad.getMatriculaList().size() > 0) {
            //Verifico las entidades hijas    
            IDaoMatriculas daoMatriculas = new DaoMatriculas(this.entityManager);
            for (Matricula elemento : entidad.getMatriculaList()) {
                respuesta.agregarMyRespuesta(daoMatriculas.verificarEntidadAlModificar(elemento));
            }
        }
        return respuesta;
    }

    @Override
    public MyRespuesta verificarEntidadAlEliminar(Usuario entidad) {
        MyRespuesta respuesta = this.verificarDatosMinimos(entidad);
        if (respuesta.getTodoOK() && entidad.getMatriculaList().size() > 0) {
            IDaoMatriculas daoMatriculas = new DaoMatriculas(this.entityManager);
            for (Matricula elemento : entidad.getMatriculaList()) {
                respuesta.agregarMyRespuesta(daoMatriculas.verificarEntidadAlEliminar(elemento));
            }
        }
        return respuesta;
    }

    //</editor-fold>
    //<editor-fold defaultstate="collapsed" desc="Implementaciones por Interfz">
    @Override
    public MyRespuesta guardarUsuario(Usuario usuario) {
        WrapperTransaction wTr = new WrapperTransaction(this.entityManager.getTransaction());
        MyRespuesta respuesta = new MyRespuesta();
        try {
            wTr.begin();
            IDaoMatriculas daoMatriculas = new DaoMatriculas(entityManager);
            for (Matricula matr :usuario.getMatriculaList()) {
                matr.setFechaAlta(Calendar.getInstance().getTime());
                respuesta.agregarMyRespuesta(daoMatriculas.verificarEntidadAlGuardar(matr));
            }
            if (respuesta.getTodoOK()) {
                respuesta.agregarMyRespuesta(this.agregarElemento(usuario));
            }
            if (respuesta.getTodoOK()) {
                wTr.commit();
            } else {
                wTr.rollback();
            }

        } catch (Exception e) {
            respuesta.addError(e.getMessage());
            wTr.rollback();
        }
        return respuesta;
    }
    //</editor-fold>

    @Override
    public MyRespuesta actualizarUsuario(Usuario usuario) {
        WrapperTransaction wTr = new WrapperTransaction(this.entityManager.getTransaction());
        MyRespuesta respuesta = new MyRespuesta();

        IDaoMatriculas daoMatriculas = new DaoMatriculas(this.entityManager);

        Usuario usuarioViejo = this.encuentraEntidad(usuario.getId());
        if (usuarioViejo == null) {
            respuesta.addError("Esta intentado modificar un usuario que no existe");
            return respuesta;
        }
        try {
            wTr.begin();

            List<Matricula> matriculasABorrar = new ArrayList<>();

            //Filtro las matriculas que estaban y ya no estan
            for (Matricula elemento : usuarioViejo.getMatriculaList()) {
                if (!usuario.getMatriculaList().contains(elemento)) {
                    matriculasABorrar.add(elemento);
                }
            }

            respuesta.agregarMyRespuesta(daoMatriculas.eliminarMatriculas(matriculasABorrar));

            if (respuesta.getTodoOK()) {
                // Modificar matriculas o guardarlas
                int i = 0;
                for (Matricula elemento : usuario.getMatriculaList()) {
                    elemento.setFechaAlta(Calendar.getInstance().getTime());
                    i++;
                    Matricula matriculaAux = daoMatriculas.encuentraEntidad(elemento.getMatricula());
                    if (matriculaAux != null) {
                        //Actualizo
                        if (!matriculaAux.getUsuario().equals(usuario)) {
                            respuesta.addError("La matricula: " + elemento.getMatricula() + " ya pertenece a otro usuario");
                        } else {
                            respuesta.agregarMyRespuesta(daoMatriculas.verificarEntidadAlModificar(elemento));
                        }
                    } else {
                        //Inserto
                        respuesta.agregarMyRespuesta(daoMatriculas.verificarEntidadAlGuardar(elemento));
                    }
                }
                if (respuesta.getTodoOK()) {
                    respuesta.agregarMyRespuesta(this.actualizarElemento(usuario));
                }
            }
            if (respuesta.getTodoOK()) {
                wTr.commit();
            } else {
                wTr.rollback();
            }

        } catch (Exception e) {
            wTr.rollback();
            respuesta.addError(e.getMessage());
        }

        return respuesta;

    }

    @Override
    public MyRespuesta eliminarUsuario(Usuario usuario) {
        return this.eliminarElemento(usuario);
    }

    @Override
    public List<Usuario> conNamedQuery(consNamed named) {
        return this.consultaNMBBDD(named);
    }

    @Override
    protected Class getClase() {
        return Usuario.class;
    }

    @Override
    public boolean tieneRegistros() {
        return this.existenRegistros();
    }

    @Override
    public Usuario encuentraEntidad(Object id) {
        return this.encuentraRegistro(Usuario.class, id);
    }

    @Override
    public Usuario encuentraPorDNI(String DNI) {
        
        consNamed parametors= new consNamed();
        parametors.setNamedQuery(Usuario.BUSCAR_POR_DNI);
        Map<String, Object> parametro = new HashMap<String, Object>();
        parametro.put(Usuario.PA_BUSCAR_DNI, DNI);
        parametors.setParametros(parametro);
        
        return this.conNamedQuery(parametors).get(0); //Como es una clave primaria sólo puede encontrar null o la entidad en si
    }


}
